home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 009a / newtk200.zip / NEWTDLL.CPP next >
C/C++ Source or Header  |  1993-03-11  |  10KB  |  501 lines

  1. // @(#) %M% V%I% %H%
  2. //
  3. // File name
  4. // -------------
  5. // NEWTDLL.CPP
  6. //
  7. // (c) Cavendish Software Ltd 1991, 1992
  8. //
  9. // Document References
  10. // -------------------
  11. // This is a general purpose module, and as such has no document references
  12. //
  13. // File Description
  14. // ----------------
  15. // Newtrack v2.0/Windows.  DLL Section of NewTrack, a new/delete and
  16. //    open/close tracking and verification system.
  17. //
  18.  
  19. // HEADER FILES
  20. #include <io.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <windows.h>
  25. #include <newtrack.hpp>
  26.  
  27.  
  28. // ENUMERATED TYPES - Errors
  29. enum TRK_ERROR
  30. {
  31.     TKE_OK = 0,                            // No error
  32.     TKE_UNDERRUN,                        // Pointer Underrun
  33.     TKE_OVERRUN,                        // Pointer Overrun
  34.     TKE_BADPTR,                            // Invalid pointer
  35.     TKE_NULLPTR,                        // NULL Pointer
  36.     TKE_NOMEMORY,                        // Out of memory
  37.     TKE_NEWLEFTOVER                        // Unfreed allocations
  38. };
  39.  
  40.  
  41. // TYPE DEFINITIONS & CLASSES
  42.  
  43. // Block Structure.  Used to track an allocation
  44. struct NT_BLOCK
  45. {
  46.     TRK_CALLER            caller;
  47.     NT_PTR                ptr;
  48.     NT_SIZE                size;
  49.     NT_BLOCK            *next;
  50.     NT_BLOCK            *prev;
  51.  
  52.     NT_BLOCK(NT_PTR _ptr, NT_SIZE _size, TRK_CALLER _caller) :
  53.         ptr(_ptr),
  54.         size(_size),
  55.         caller(_caller),
  56.  
  57.         next(0),
  58.         prev(0)
  59.     {
  60.         // Nothing
  61.     }
  62.  
  63.     ~NT_BLOCK(void)
  64.         { ptr = 0; size = 0; next = 0; prev = 0; caller = 0; }
  65. };
  66.  
  67. // Task Structure.  Contains info for a task
  68. struct NT_TASK
  69. {
  70.     HTASK                taskid;
  71.     int                    tracking;
  72.     TRK_ERROR            error;
  73.     NT_BLOCK            *blocks;
  74.     unsigned long        nallocs;
  75.     NT_TASK                *next;
  76.     NT_TASK                *prev;
  77.  
  78.                         NT_TASK(int _tracking = 0) :
  79.                             tracking(_tracking),
  80.                             error(TKE_OK),
  81.                             blocks(0),
  82.                             nallocs(0),
  83.                             next(0),
  84.                             prev(0)
  85.                         {
  86.                             taskid = GetCurrentTask();
  87.                         }
  88.  
  89.     // Adds a block to the list 
  90.             void        AddBlock(NT_PTR p, NT_SIZE size, TRK_CALLER caller);
  91.  
  92.     // Removes a block from the list
  93.             void        ExtractBlock(NT_BLOCK *blk);
  94.  
  95.     // Validates a pointer, calling the error handler if invalid
  96.             NT_BLOCK    *ValidPtr(NT_PTR p);
  97.  
  98.     // Error handler
  99.             void        HandleError(TRK_ERROR err, unsigned long count = 0);
  100. };
  101.  
  102.  
  103. // GLOBAL VARIABLES -- Error Messages
  104. static char *errmsgs[]=
  105. {
  106.     "No Error!",
  107.     "Pointer Underrun",
  108.     "Pointer Overrun",
  109.     "Invalid Pointer Passed to Delete",
  110.     "NULL Pointer Allocation",
  111.     "Out of Memory",
  112.     "%lu Unfreed Memory Allocations"
  113. };
  114.  
  115.  
  116. // GLOBAL VARIABLES
  117. static NT_TASK    *tasklist = 0;
  118.  
  119.  
  120. // GLOBAL VARIABLES -- EXTERNALS
  121. #ifndef __DLL__
  122. extern    int        __newtrack;
  123. #endif
  124.  
  125.  
  126. // FUNCTION PROTOTYPES
  127. NT_TASK    *NT_FindTask(void);
  128. void    _hmemset(NT_PTR p, int c, NT_SIZE n);
  129. void    _hmemcpy(NT_PTR dest, NT_PTR src, NT_SIZE n);
  130. int        _hmemcmp(NT_PTR s1, NT_PTR s2, NT_SIZE n);
  131.  
  132.  
  133.  
  134.  
  135.  
  136. //
  137. //
  138. // Methods for Class: NT_TASK
  139. //
  140. //
  141. void NT_TASK::AddBlock(NT_PTR p, NT_SIZE size, TRK_CALLER caller)
  142. {
  143.     // Turn off NewTrack tracking to prevent loopback
  144. #ifndef __DLL__
  145.     __newtrack = 0;
  146. #endif
  147.  
  148.     // Create a new block
  149.     NT_BLOCK *blk = new NT_BLOCK(p, size, caller);
  150.  
  151.     // Turn NewTrack tracking back on
  152. #ifndef __DLL__
  153.     __newtrack = 1;
  154. #endif
  155.  
  156.     // If there is already a list...
  157.     if (blocks)
  158.     {
  159.         // Find the last in the list
  160.         NT_BLOCK *b2 = blocks;
  161.         for (; b2->next; b2 = b2->next)
  162.             ;
  163.  
  164.         // Tack the new block onto the end
  165.         b2->next = blk;
  166.         blk->prev = b2;
  167.     }
  168.     else
  169.  
  170.     // No list yet, so start it off...
  171.         blocks = blk;
  172.  
  173.     // Increase count of allocations
  174.     nallocs++;
  175. }
  176.  
  177. void NT_TASK::ExtractBlock(NT_BLOCK *blk)
  178. {
  179.     // Point the previous block around 
  180.     if (blk->prev)
  181.         blk->prev->next = blk->next;
  182.     else
  183.         blocks = blk->next;
  184.  
  185.     // Point the next block around
  186.     if (blk->next)
  187.         blk->next->prev = blk->prev;
  188.  
  189.     // Decrease the number of allocations
  190.     nallocs--;
  191. }
  192.  
  193. // Validates the pointer as being allocated via NewTrack
  194. NT_BLOCK *NT_TASK::ValidPtr(NT_PTR p)
  195. {
  196.     NT_BLOCK    *blk = blocks;
  197.  
  198.     // See if we can find a match for the pointer
  199.     for (; blk; blk = blk->next)
  200.         if (blk->ptr == p)
  201.             break;
  202.  
  203.     // If no match...
  204.     if (!blk)
  205.     {
  206.         // Tell the user
  207.         HandleError(TKE_BADPTR);
  208.         return 0;
  209.     }
  210.  
  211.     // Check the pre-text is still there
  212.     if (_hmemcmp(p, (NT_PTR) NT_PRE_TEXT, NT_PRE_SIZE) != 0)
  213.     {
  214.         // Tell the user
  215.         HandleError(TKE_UNDERRUN);
  216.         return 0;
  217.     }
  218.  
  219.     // Check the post-text is still there
  220.     if (_hmemcmp(p + blk->size - NT_POST_SIZE, (NT_PTR) NT_POST_TEXT,
  221.         NT_POST_SIZE) != 0)
  222.     {
  223.         // Tell the user
  224.         HandleError(TKE_OVERRUN);
  225.         return 0;
  226.     }
  227.  
  228.     // The pointer is valid....return the block
  229.     return blk;
  230. }
  231.  
  232. // Tells the user abouts the error, with the option to terminate app.
  233. void NT_TASK::HandleError(TRK_ERROR err, unsigned long count)
  234. {
  235.     char tmps[500];
  236.     sprintf(tmps, errmsgs[err], count);
  237.     strcat(tmps, " - Continue?");
  238.  
  239.     // Tell the user
  240.     int ret = MessageBox(0, tmps, "NewTrack Error", MB_SYSTEMMODAL |
  241.         MB_ICONSTOP | MB_OKCANCEL);
  242.  
  243.     // Abort the app if requested
  244.     if (ret != IDOK)
  245.         abort();
  246.  
  247.     // Break into the debugger                        
  248.     asm int 3;
  249. }
  250.  
  251.  
  252.  
  253.  
  254.  
  255. // FUNCTIONS
  256.  
  257. // Initialises NewTrack tracking for the current task
  258. void _far _pascal NT_Initialise(void)
  259. {
  260.     // Allocate Task info
  261.     NT_TASK    *task = new NT_TASK(1);
  262.  
  263.     // If this is the first task to use NewTrack, start the list off
  264.     if (!tasklist)
  265.         tasklist = task;
  266.     else
  267.     {
  268.         NT_TASK *last;
  269.  
  270.         // Find the last task in the list
  271.         for (last = tasklist; last->next; last = last->next)
  272.             ; // Nothing
  273.  
  274.         // Add a new one onto the end
  275.         last->next = task;
  276.         task->prev = last;
  277.     }
  278. }
  279.  
  280. // Terminates NewTrack tracking for the current task
  281. unsigned long _far _pascal NT_Terminate(void)
  282. {
  283.     unsigned long    nallocs;
  284.     NT_BLOCK        **blist = 0;
  285.     NT_TASK            *task = NT_FindTask();
  286.  
  287.     // If there are any unfreed pointers (for this task)
  288.     if ((nallocs = task->nallocs) > 0)
  289.     {
  290.         unsigned blsize;
  291.  
  292.         // Make sure we can handle the number
  293.         if (nallocs > 0xfffe)
  294.             blsize = 0xfffe;
  295.         else
  296.             blsize = (unsigned) nallocs;
  297.  
  298.         // Tell the user
  299.         task->HandleError(TKE_NEWLEFTOVER, nallocs);
  300.  
  301.         // Create a shorthand array of unfreed blocks 
  302.         blist = new NT_BLOCK *[blsize + 1];
  303.  
  304.         // If we made it...
  305.         if (blist)
  306.         {
  307.             unsigned    i;
  308.             NT_BLOCK    *blk = task->blocks;
  309.  
  310.             // Make up the list of unfreed blocks for this task
  311.             for (i = 0; blk; blk = blk->next, i++)
  312.                 blist[i] = blk;
  313.  
  314.             // Terminate the list
  315.             blist[i] = 0;
  316.         }
  317.     }
  318.  
  319.     // If there are any unfreed allocs, break into the debugger
  320.     if (blist)
  321.     {
  322.         asm int 3
  323.  
  324.         // Free up the shorthand list
  325.         if (blist)
  326.             delete blist;
  327.     }
  328.  
  329.     // Point the previous task around us
  330.     if (task->prev)
  331.         task->prev->next = task->next;
  332.     else
  333.         tasklist = task->next;
  334.  
  335.     // Point the next task around us
  336.     if (task->next)
  337.         task->next->prev = task->prev;
  338.  
  339.     // Return number of allocations left over
  340.     return nallocs;
  341. }
  342.  
  343. // Transforms a pointer p into a NewTrack pointer by adding a
  344. //    header & trailer.
  345. NT_PTR _far _pascal NT_New(void far *_p, NT_SIZE size, TRK_CALLER caller)
  346. {
  347.     NT_TASK        *task = NT_FindTask();
  348.     NT_PTR        p = (NT_PTR) _p;
  349.  
  350.     // If tracking is turned off, drop out straight away
  351.     if (!task || !task->tracking)
  352.         return p;
  353.  
  354.     // If we ran out of memory, tell the user
  355.     if (!p)
  356.     {
  357.         task->HandleError(TKE_NOMEMORY);
  358.         return 0;
  359.     }
  360.  
  361.     // Set the pre-text and post-text, and initialise the rest 
  362.     _hmemcpy(p, (NT_PTR) NT_PRE_TEXT, NT_PRE_SIZE);
  363.     _hmemcpy(p + size - NT_POST_SIZE, (NT_PTR) NT_POST_TEXT, NT_POST_SIZE);
  364.     _hmemset(p + NT_PRE_SIZE, NT_NEWFILL, size - NT_PRE_SIZE - NT_POST_SIZE);
  365.  
  366.     // Add the block to the tasks' list
  367.     task->AddBlock(p, size, caller);
  368.  
  369.     // Return the pointer *after* our pre-text
  370.     return p + NT_PRE_SIZE;
  371. }
  372.  
  373. // Transforms a NewTrack pointer into an oridinary pointer by
  374. //    removing the header.
  375. void far * _far _pascal NT_Delete(NT_PTR p)
  376. {
  377.     NT_TASK        *task = NT_FindTask();
  378.     NT_BLOCK    *blk;
  379.  
  380.     // Is there any tracking running at all?
  381.     if (!task || !task->tracking)
  382.         return p;
  383.  
  384.     // Restore the pointer to that returned by malloc()
  385.     p -= NT_PRE_SIZE;
  386.  
  387.     // If we have a valid pointer
  388.     if ((blk = task->ValidPtr(p)) != 0)
  389.     {
  390.         // Extract block from the list
  391.         task->ExtractBlock(blk);
  392.  
  393.         // Fill in the block with known "garbage"
  394.         _hmemset(p, NT_DELFILL, blk->size);
  395.  
  396.         // Turn off NewTrack tracking to prevent loopback
  397. #ifndef __DLL__
  398.         __newtrack = 0;
  399. #endif
  400.  
  401.         // Delete the block
  402.         delete blk;
  403.  
  404.         // Turn NewTrack tracking back on
  405. #ifndef __DLL__
  406.         __newtrack = 1;
  407. #endif
  408.     }
  409.     else
  410.         return 0;
  411.  
  412.     // Return the pointer to be freed by the real task
  413.     return (void far *)p;
  414. };
  415.  
  416. // Finds the NT_TASK structure for the current task
  417. NT_TASK    *NT_FindTask(void)
  418. {
  419.     NT_TASK    *task = tasklist;
  420.  
  421.     // Find the NT_TASK for the current task
  422.     for (; task; task = task->next)
  423.         if (task->taskid == GetCurrentTask())
  424.             break;
  425.  
  426.     // Return the found task
  427.     return task;
  428. }
  429.  
  430. // Returns the number of allocations
  431. unsigned long NT_EXPORT _far _pascal NT_NAllocs(void)
  432. {
  433.     NT_TASK        *task = NT_FindTask();
  434.  
  435.     return (task) ? task->nallocs : 0;
  436. }
  437.  
  438. // Returns the real size to allocate; called by new() so that the task can allocate
  439. NT_SIZE _far _pascal NT_NewSize(unsigned long size)
  440. {
  441.     return size + NT_PRE_SIZE + NT_POST_SIZE;
  442. }
  443.  
  444.  
  445.  
  446.  
  447.  
  448. //
  449. //
  450. // Helper functions
  451. //
  452. //
  453.  
  454. // Huge memset() - sets n bytes of data to c
  455. void _hmemset(NT_PTR p, int c, NT_SIZE n)
  456. {
  457.     for (; n; p++, n--)
  458.         *p = c;
  459. }
  460.  
  461. // Huge memcpy() - copies n bytes from src to dest
  462. void _hmemcpy(NT_PTR dest, NT_PTR src, NT_SIZE n)
  463. {
  464.     for (; n; n--, dest++, src++)
  465.         *dest = *src;
  466. }
  467.  
  468. // Huge memcmp() - compares n bytes of s1 with s2
  469. int  _hmemcmp(NT_PTR s1, NT_PTR s2, NT_SIZE n)
  470. {
  471.     for (; n && *s1 == *s2; n--, s1++, s2++)
  472.         ;
  473.  
  474.     return (n) ? ((int)(s1 - s2)) : 0;
  475. }
  476.  
  477.  
  478.  
  479.  
  480.  
  481. //
  482. //
  483. // DLL specific Functions
  484. //
  485. //
  486. #ifdef __DLL__
  487. #pragma argsused
  488. int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine)
  489. {
  490.     if (wHeapSize != 0)
  491.         UnlockData(0);
  492.     return (1);
  493. }
  494.  
  495. #pragma argsused
  496. int FAR PASCAL WEP(int bSystemExit)
  497. {
  498.     return (1);
  499. }
  500. #endif
  501.